package com.a0soft.gphone.aTruffleHog.di;
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 3, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * Copyright(C) 2011 
 *   Sam Lu <ysl.sam.lu (at) gmail.com>
 *
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import com.a0soft.gphone.aTruffleHog.util.CONSTS;
import com.a0soft.gphone.aTruffleHog.util.MiscUtil;
import com.a0soft.gphone.aTruffleHog.util.aDebug;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

public class GoldenInfo {
    private Context m_ctx;
    private boolean m_bIsGoldenChangedInited;
    private boolean m_bIsGoldenChanged;

    private static GoldenInfo m_inst;

    private static String DIR_NAME = CONSTS.DATA_DIR_NAME;
    private static String FILE_NAME = "golden.info";

    private static String LOG_TAG = GoldenInfo.class.getSimpleName();

    // //////////////////////////////////////////////////////
    public static GoldenInfo 
    GetInstance(Context ctx)
    {
        if (m_inst == null) {
            m_inst = new GoldenInfo(ctx);
        }

        return m_inst;
    }

    private 
    GoldenInfo(Context ctx)
    {
        m_ctx = ctx;
    }

    /**
     * @return true if * user ID changed * model ID changed * SIM card changed *
     *         rooted * flash a new ROM or OS patched
     */
    public boolean 
    IsGoldenChanged()
    {
        if (m_bIsGoldenChangedInited)
            return m_bIsGoldenChanged;

        final String strGoldenMD5 = _Read(m_ctx);
        String strNewGoldenMD5 = _GetGoldenMD5();

        if (aDebug.ENABLED) {
            aDebug.d(LOG_TAG, "IsGoldenChanged()");
            aDebug.d(LOG_TAG, "  old MD5=" + strGoldenMD5);
            aDebug.d(LOG_TAG, "  new MD5=" + strNewGoldenMD5);
        }

        if (!TextUtils.isEmpty(strGoldenMD5) && // has golden
            strNewGoldenMD5.equals(strGoldenMD5)) {// and golden not changed
            m_bIsGoldenChanged = false;
        }
        else {
            m_bIsGoldenChanged = true;
        }
        
        m_bIsGoldenChangedInited = true;
        return m_bIsGoldenChanged;
    }

    public void 
    UnsetGoldenChanged()
    {
        if (m_bIsGoldenChangedInited) {
            m_bIsGoldenChanged = false;

            String strNewGoldenMD5 = _GetGoldenMD5();
            _Write(m_ctx, strNewGoldenMD5);
        }
    }

    private String 
    _GetGoldenMD5()
    {
        StringBuilder sb = new StringBuilder(1024);
        sb.append(UserInfo.GetUserID())
          .append(UserInfo.GetCountryCode())
          .append(SysInfo.GetMID())
          .append(CONSTS.INK_VERSION);

        TelephonyManager tm = (TelephonyManager) m_ctx
                                .getSystemService(Context.TELEPHONY_SERVICE);
        sb.append(tm.getSimOperator());
        sb.append(tm.getSimCountryIso());
        sb.append(tm.getNetworkCountryIso());
        try {
            sb.append(tm.getSimSerialNumber()); //need READ_PHONE_STATE
        } catch (Exception e) {}
        
        
        sb.append(SysInfo.IsRootDevice())
          .append(SysInfo.GetFormattedKernelVersion())
          .append(Build.BOARD)
          .append(Build.BRAND)
          .append(Build.DEVICE)
          .append(Build.DISPLAY)
          .append(Build.FINGERPRINT)
          .append(Build.HOST)
          .append(Build.ID)
          .append(Build.MANUFACTURER)
          .append(Build.MODEL)
          .append(Build.PRODUCT)
          .append(Build.TAGS)
          .append(Build.TIME)
          .append(Build.TYPE)
          .append(Build.USER)
          .append(Build.VERSION.SDK_INT) //10
          .append(Build.VERSION.RELEASE); //2.3.4 or 2.3.6

        return MiscUtil.MD5(sb.toString());
    }

    private void 
    _Write(Context ctx, String strMD5)
    {
        new WriteTask(ctx, strMD5).execute();
    }

    private String 
    _Read(Context ctx)
    {
        if (aDebug.ENABLED)
            aDebug.d(LOG_TAG, "_Read(): start");

        File fDir = ctx.getDir(DIR_NAME, Context.MODE_PRIVATE);
        File fFile = new File(fDir, FILE_NAME);
        if (!fFile.exists() || !fFile.canRead())
            return null;

        BufferedReader br = null;
        try {
            StringBuilder sb = new StringBuilder();

            br = new BufferedReader(new FileReader(fFile), 256);
            char[] chBuf = new char[256];
            int n;
            while ((n = br.read(chBuf)) >= 0) {
                sb.append(chBuf, 0, n);
            }
            br.close();
            br = null;

            if (aDebug.ENABLED)
                aDebug.d(LOG_TAG, "_Read(): finished");

            if (sb.length() == 0)
                return null;
            else
                return sb.toString();
        }
        catch (IOException e) {
            if (aDebug.ENABLED)
                aDebug.d(LOG_TAG, "_Read()", e);

            if (br != null) {
                try {
                    br.close();
                }
                catch (IOException e1) {
                    if (aDebug.ENABLED)
                        aDebug.d(LOG_TAG, "_Read()", e);
                }
            }
        }
        return null;
    }

    // //////////////////////////////////////////////////////////////////////
    private static class WriteTask extends AsyncTask<Void, Void, Boolean> {
        private Context m_ctx;
        private String m_str;

        WriteTask(Context ctx, String str)
        {
            m_ctx = ctx;
            m_str = str;
        }

        @Override protected Boolean 
        doInBackground(Void... objs)
        {
            if (aDebug.ENABLED)
                aDebug.d(LOG_TAG, "WriteTask::doInBackground(): start");
            File fDir = m_ctx.getDir(DIR_NAME, Context.MODE_PRIVATE);
            File fFile = new File(fDir, FILE_NAME);

            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new FileWriter(fFile));
                bw.write(m_str);
                bw.close();
                bw = null;

                if (aDebug.ENABLED)
                    aDebug.d(LOG_TAG, "WriteTask::doInBackground(): finished");
                return true;
            }
            catch (IOException e) {
                if (aDebug.ENABLED)
                    aDebug.d(LOG_TAG, "WriteTask::doInBackground():", e);

                if (bw != null) {
                    try {
                        bw.close();
                    }
                    catch (IOException e1) {
                        if (aDebug.ENABLED)
                            aDebug
                                  .d(LOG_TAG, "WriteTask::doInBackground():", e);
                    }
                }
                return false;
            }
        }
    }
}
